package app.htby.utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

public class Hex {
    /**
     * 16进制工具类
     *
     * @author dwzhang
     * @version 1.0 13-7-11 上午11:03
     */
    public static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;

    public static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
            'F'};

    public static final byte[] HEX_BYTES = {(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
            (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D',
            (byte)'E', (byte)'F'};

    /** Table for HEX to DEC byte translation. */
    public static final int[] DEC = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1,
            10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1,};


    public static final String format(byte[] bytes, int lineSize, char sep)
    {
        if (bytes == null) {
            return null;
        }
        int len = bytes.length;
        if (len == 0) {
            return null;
        }

        StringBuilder sb = new StringBuilder(len * 2);
        int lineCount = 0;
        for (int i = 0; i < len; i++) {
            sb.append(HEX_CHARS[(bytes[i] >> 4) & 0xF]);
            sb.append(HEX_CHARS[(bytes[i]) & 0xF]);
            lineCount++;
            if (lineCount == lineSize) {
                sb.append("\r\n");
                lineCount = 0;
            }
            else if (i < len - 1) {
                sb.append(sep);
            }
        }
        return sb.toString();
    }

    public static final String formatByte2String(byte[] bytes)
    {
        if (bytes == null) {
            return null;
        }
        int len = bytes.length;
        if (len == 0) {
            return null;
        }

        StringBuilder sb = new StringBuilder(len * 2);
        int lineCount = 0;
        for (int i = 0; i < len; i++) {
            sb.append(HEX_CHARS[(bytes[i] >> 4) & 0xF]);
            sb.append(HEX_CHARS[(bytes[i]) & 0xF]);
            lineCount++;
        }
        return sb.toString();

    }
    /**
     *
     * int 4转换byte
     * */
    public static byte[] intToDword(int dec){
        byte [] bytes = new byte[4];
        int temp = dec;
        bytes[0] = (byte)(temp%256);
        temp = temp/256;
        bytes[1] = (byte)(temp%256);
        temp = temp/256;
        bytes[2] = (byte)(temp%256);
        temp = temp/256;
        bytes[3] = (byte)(temp%256);
        return bytes;
    }
    
    /**
     * @Title: intToByteArrayDesc
     * @Description: int转成长度为length的byte数组
     * @param @param data
     * @param @param length
     * @param @return    参数
     * @return byte[]    返回类型
     * @throws
     */
	public static byte[] intToByteArrayDesc(int data,int length) {
		length = Math.abs(length);
		if(length == 0){
			return null;
		}
		byte[] result = new byte[length];
		// 由高位到低位
		int index = 0;
		while(index < length){
			result[index] = (byte) ((data >> ((length - 1 - index)*8)) & 0xFF);
			index++;
		}
		return result;
	}
	
	/**
	 * @Title: byteArrayToIntDesc
	 * @Description: 将length长度的bytes数组转成int
	 * @param @param bytes
	 * @param @param length
	 * @param @return    参数
	 * @return int    返回类型
	 * @throws
	 */
	public static int byteArrayToIntDesc(byte[] bytes,int length) {
		int value = 0;
		length = Math.abs(length);
		if(length == 0){
			return value;
		}
		// 由高位到低位
		int index = 0;
		while(index < length){
			value += (bytes[index] & 0x000000FF) << ((length - 1 - index) * 8);// 往高位游
			index++;
		}
		return value;
	}
    
	/**
	 * int到byte[]
	 * 
	 * @param i
	 * @return
	 */
	public static byte[] intToByteArray(int i) {
		byte[] result = new byte[4];
		// 由高位到低位
		result[0] = (byte) ((i >> 24) & 0xFF);
		result[1] = (byte) ((i >> 16) & 0xFF);
		result[2] = (byte) ((i >> 8) & 0xFF);
		result[3] = (byte) (i & 0xFF);
		return result;
	}

	/**
	 * byte[]转int
	 * 
	 * @param bytes
	 * @return
	 */
	public static int byteArrayToInt(byte[] bytes) {
		int value = 0;
		// 由高位到低位
		for (int i = 0; i < 4; i++) {
			int shift = (4 - 1 - i) * 8;
			value += (bytes[i] & 0x000000FF) << shift;// 往高位游
		}
		return value;
	}

    /**
     * BCDW
     * String 转换2位byte
     * */
    public static byte[] str2Bcd(String asc)
    {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        if (len >= 2) {
            len = len / 2;
        }
        byte bbt[] = new byte[len];
        byte abt[] = asc.getBytes();
        int j, k;
        for (int p = 0; p < asc.length() / 2; p++) {
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
                j = abt[2 * p] - '0';
            }
            else {
                if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
                    j = abt[2 * p] - 'a' + 0x0a;
                }
                else {
                    j = abt[2 * p] - 'A' + 0x0a;
                }
            }
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
                k = abt[2 * p + 1] - '0';
            }
            else {
                if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
                    k = abt[2 * p + 1] - 'a' + 0x0a;
                }
                else {
                    k = abt[2 * p + 1] - 'A' + 0x0a;
                }
            }
            int a = (j << 4) + k;
            byte b = (byte)a;

            bbt[p] = b;

        }
        return bbt;
    }

    public static String[] bytesToHexStrings(byte[] src){
        if (src == null || src.length <= 0) {
            return null;
        }
        String[] str = new String[src.length];
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                str[i] = "0";
            }
            str[i] = hv;
        }
        return str;
    }

    //顺序转换
    public static int[] ArrayTwo(int[] arrayOne){
        for(int i=0;i<arrayOne.length/2;i++){
            int tmp = arrayOne[i];
            arrayOne[i]=arrayOne[arrayOne.length-1-i];
            arrayOne[arrayOne.length-1-i] = tmp;
        }
        return arrayOne;
    }


    public static final int formatByteToInt(byte[] bytes )
    {
        if (bytes == null) {
            return -1;
        }
        int len = bytes.length ;
        if (len == 0) {
            return -1;
        }
        int [] sw = new int [len] ;
        int num = 0 ;
        for (int i = 0 ; i < len; i++) {
            sw[i] = ((bytes[ i]>>4)&0x0f)*16+(bytes[i]&0x0f);
        }
        for (int i = sw.length-1; i >= 0 ; i--) {
            num += sw[i] *(int) Math.pow(256, i);
        }
        return num;
    }
    /**
     * byte 转int 10
     * */
    public static final int formatByteToInt2(byte[] bytes )
    {
        if (bytes == null) {
            return -1;
        }
        int len = bytes.length ;
        if (len == 0) {
            return -1;
        }
        int [] sw = new int [len] ;
        int num = 0 ;
        for (int i = 0 ; i < len; i++) {
            sw[i] = ((bytes[ i]>>4)&0x0f)* 16 +(bytes[i]&0x0f);
        }
        for (int i = 0 ; i < sw.length ; i++) {
            num += sw[i] *(int) Math.pow(256, sw.length-1-i);
        }
        return num;
    }

    public static ByteBuffer createByteBuffer(int length)
    {
        ByteBuffer bf = ByteBuffer.allocate(length);
        bf.order(BYTE_ORDER);
        bf.rewind();
        return bf;
    }
    /**
     * String 转 byte[]
     * */
    public static byte[] string2Bytes(String s, int length, String encoding)
    {
        ByteBuffer bf = createByteBuffer(length);
        if (isEmpty(s)) {
            bf.put(new byte[length]);
        }
        else {
            try {
                byte[] array = s.getBytes(encoding);
                int len = array.length > length ? length : array.length;
                bf.put(array, 0, len);
            }
            catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Can't get bytes for encoding " + encoding);
            }
        }
        bf.flip();
        return bf.array();
    }
    /**
     *BCD转为10进制
     * */
    public static String bcd2Str(byte[] bytes) {
        StringBuffer temp = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp.
                toString().substring(1) : temp.toString();
    }
    
    /**
     * @Title: string2Bytes
     * @Description: 字符串转byte数组，GBK（中文）编码
     * @param @param s
     * @param @param length
     * @param @return    参数
     * @return byte[]    返回类型
     * @throws
     */
    public static byte[] string2Bytes(String s, int length)
    {
        return string2Bytes(s, length, "GBK");
    }
    
    /**
     * @Title: stringToBytes
     * @Description: 字符串转byte数组，UTF-8编码
     * @param @param s
     * @param @param length
     * @param @return    参数
     * @return byte[]    返回类型
     * @throws
     */
    public static byte[] stringToBytes(String s, int length)
    {
        return string2Bytes(s, length, "UTF-8");
    }
    
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * GDK转换中文
     * */
    public static String  formatByteToStringGBK(byte[] bytes) {
        String s=formatByte2String(bytes);
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            }
        }
        try {
            s = new String(baKeyword, "GBK");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
            return "";
        }
        return s;
    }
    /**
     * GDK转换2进制
     * */
    public static String formatByteToString2(byte[] bytes)
    {
        StringBuffer sb = new StringBuffer(Hex.formatByte2String(bytes));
//		sb.reverse();
        String hexString=sb.substring(2)+sb.substring(0,2);
        System.out.println(hexString);
        if (hexString == null || hexString.length() % 2 != 0)
            return null;
        String bString = "", tmp;
        for (int i = 0; i < hexString.length(); i++)
        {
            tmp = "0000"
                    + Integer.toBinaryString(Integer.parseInt(hexString
                    .substring(i, i + 1), 16));
            bString += tmp.substring(tmp.length() - 4);
        }
        return bString;
    }
    //2转16
    public static String binaryToHex(String binaryStr){
        String binarys[] = new String[]{
                "0000","0001","0010","0011",
                "0100","0101","0110","0111",
                "1000","1001","1010","1011",
                "1100","1101","1110","1111"
        };
        String hexs[] = new String[]{
                "0","1","2","3",
                "4","5","6","7",
                "8","9","A","B",
                "C","D","E","F"
        };
        int n = binaryStr.length()%4;
        if(n != 0){
            int zeroNum = 0;
            zeroNum = 4 - n;
            for(int i=0; i< zeroNum; i++){
                binaryStr = "0"+binaryStr;
            }
            n = n+1;
        }
        String hexStr = "";
        for(int j=0; j<binaryStr.length()/4; j++){
            String temp = binaryStr.substring(j*4, (j+1)*4);
            int index = -1;
            for(int k=0;k<16;k++){
                if(binarys[k].equals(temp)){
                    index = k;
                }
            }
            if(index != -1){
                hexStr = hexStr + hexs[index];
            }
        }

        return hexStr;
    }
    //int 转换byte[]
    public static byte[] int2byte(int res,int length) {
        byte[] targets = new byte[length];

        targets[3] = (byte) (res & 0xff);// 最低位
        targets[2] = (byte) ((res >> 8) & 0xff);// 次低位
        targets[1] = (byte) ((res >> 16) & 0xff);// 次高位
        targets[0] = (byte) (res >>> 24);// 最高位,无符号右移。
        return targets;
    }
    /**
     * 二进制字符串转换为byte数组,每个字节以","隔开
     * **/
    public static byte[] conver2HexToByte(String hex2Str)
    {
        String [] temp = hex2Str.split(",");
        byte [] b = new byte[temp.length];
        for(int i = 0;i<b.length;i++)
        {
            b[i] = Long.valueOf(temp[i], 2).byteValue();
        }
        return b;
    }
    /**
     * 将short转为高字节在前，低字节在后的byte数组
     * @param n short
     * @return byte[]
     */
    public static byte[] toHH(short n) {
        byte[] b = new byte[2];
        b[1] = (byte) (n & 0xff);
        b[0] = (byte) (n >> 8 & 0xff);
        return b;
    }
    
    /*********************************** long与byte[]之间的转换 ***********************************/
//	private static ByteBuffer buffer = ByteBuffer.allocate(8); 
	
	/**
	 * @Title: longToBytes
	 * @Description: long 转成 byte 数组
	 * @param @param x
	 * @param @return    参数
	 * @return byte[]    返回类型
	 * @throws
	 */
    public static byte[] longToBytes(long x) {
    	ByteBuffer buffer = ByteBuffer.allocate(8); 
        buffer.putLong(0, x);
        return buffer.array();
    }

    /**
     * @Title: bytesToLong
     * @Description: byte 数组转成 long 
     * @param @param bytes
     * @param @return    参数
     * @return long    返回类型
     * @throws
     */
    public static long bytesToLong(byte[] bytes) {
    	ByteBuffer buffer = ByteBuffer.allocate(8); 
    	System.out.println("时间转换："+Arrays.toString(bytes));
        buffer.put(bytes, 0, bytes.length);
        buffer.flip();//need flip 
        return buffer.getLong();
    }
    /*********************************** long与byte[]之间的转换 ***********************************/
}